package com.example.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.model.BlockchainOp;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.config.ConfigOption;
import org.fisco.bcos.sdk.config.model.ConfigProperty;
import org.fisco.bcos.sdk.utils.ThreadPoolService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * Http方式请求WeBASE-Front
 */
@Service
public class WeBASEUtils {

    @Value("${project.webase-url}")
    String webaseUrl;

    @Value("${system.contract.PensionInsuranceTransferAddress}")
    String contractAddress;

    public static final String ABI = com.example.utils.IOUtil.readResourceAsString("abi/PensionInsuranceTransfer.abi");

    /**
     * 发送 post 请求调用链接口
     * 
     * @param userAddress
     * @param funcName
     * @param funcParam
     * @return 请求结果
     */
    public String funcPost(String userAddress, String funcName, List funcParam) {
        JSONArray abiJSON = JSONUtil.parseArray(ABI);
        // 负载
        JSONObject data = JSONUtil.createObj();
        data.set("groupId", "group0");
        data.set("contractPath", "/");
        data.set("contractAbi", abiJSON);
        data.set("useAes", false);
        data.set("useCns", false);
        data.set("cnsName", "");
        data.set("user", userAddress);
        data.set("contractAddress", contractAddress);
        data.set("funcName", funcName);
        data.set("funcParam", funcParam);

        String dataString = JSONUtil.toJsonStr(data);

        // 创建httpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 创建post请求方式实例
        HttpPost httpPost = new HttpPost(webaseUrl);
        // 设置请求头 发送的是json数据格式
        httpPost.setHeader("Content-type", "application/json;charset=utf-8");
        // 设置参数---设置消息实体 也就是携带的数据
        StringEntity entity = new StringEntity(dataString, Charset.forName("UTF-8"));
        // 设置编码格式
        entity.setContentEncoding("UTF-8");
        // 发送Json格式的数据请求
        entity.setContentType("application/json");
        // 把请求消息实体塞进去
        httpPost.setEntity(entity);
        // 执行http的post请求
        CloseableHttpResponse httpResponse;
        String result = null;

        try {
            httpResponse = httpClient.execute(httpPost);
            result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(result);

        return result;
    }

    /**
     * 获取用户最近的区块链操作记录
     * 
     * @param userAddress 用户地址
     * @param limit       限制条数
     * @return 区块链操作记录列表
     */
    public List<BlockchainOp> getRecentOps(String userAddress, int limit) {
        try {
            // 调用区块链接口获取操作的基本信息
            String basicInfoResult = funcPost(userAddress, "getOperationHistoryPagedBasic",
                    List.of(userAddress, 0, limit));

            // 调用区块链接口获取区块链信息
            String blockInfoResult = funcPost(userAddress, "getOperationHistoryPagedBlockchain",
                    List.of(userAddress, 0, limit));

            // 解析返回结果
            JSONArray basicInfoArray = JSONUtil.parseArray(basicInfoResult);
            JSONArray blockInfoArray = JSONUtil.parseArray(blockInfoResult);

            if (ObjectUtil.isNull(basicInfoArray) || ObjectUtil.isNull(blockInfoArray)) {
                return new ArrayList<>();
            }

            List<BlockchainOp> opsList = new ArrayList<>();

            // 处理两种不同格式的返回数据
            int minSize = Math.min(basicInfoArray.size(), blockInfoArray.size());
            for (int i = 0; i < minSize && i < limit; i++) {
                // 解析基本信息
                JSONArray basicInfo = JSONUtil.parseArray(basicInfoArray.getStr(i));
                // 解析区块链信息
                JSONArray blockInfo = JSONUtil.parseArray(blockInfoArray.getStr(i));

                BlockchainOp op = BlockchainOp.builder()
                        .opId("OP" + System.currentTimeMillis() + i)
                        .userAddress(userAddress)
                        .opType(basicInfo.size() > 0 ? basicInfo.getStr(0) : "UNKNOWN")
                        .description(basicInfo.size() > 1 ? basicInfo.getStr(1) : "")
                        .opTime(LocalDateTime.now())
                        .txHash(blockInfo.size() > 0 ? blockInfo.getStr(0) : "")
                        .blockHeight(blockInfo.size() > 1 ? blockInfo.getLong(1) : 0L)
                        .blockTimestamp(blockInfo.size() > 2 ? blockInfo.getLong(2) : System.currentTimeMillis())
                        .build();

                opsList.add(op);
            }

            return opsList;
        } catch (Exception e) {
            System.err.println("获取区块链操作记录异常: " + e.getMessage());
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

}
